package com.spzx.common.redis.aspect;

import com.spzx.common.redis.annotation.XingXingCache;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName XingXingCacheAspect
 * @Author 波
 * @Date 2024/8/7 18:56
 */
@Slf4j
@Aspect
public class XingXingCacheAspect {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @SneakyThrows
    @Around("@annotation(xingXingCache)")
    public Object around(ProceedingJoinPoint joinPoint, XingXingCache xingXingCache) {
        //返回的类型
        Object object;
        //设置dataKey从缓存查询数据
        String prefix = xingXingCache.prefix();
        Object[] args = joinPoint.getArgs();
        String paramVal = "none";
        try {
            if (args != null && args.length > 0) {
                paramVal = Arrays.asList(args).stream().map(item -> item.toString()).collect(Collectors.joining(":"));
            }
            String dataKey = prefix + paramVal;
            object = redisTemplate.opsForValue().get(dataKey);
            //如果从缓存中查到了数据就返回
            if (redisTemplate.opsForValue().get(dataKey) != null) {
                return object;
            }

            //如果从缓存中查不到数据，那就获取分布式锁
            String lockKey = dataKey + ":lock";
            RLock lock = redissonClient.getLock(lockKey);
            lock.lock();
            try {
                object = joinPoint.proceed(args);
                int ttl = object == null ? 60 : 10 * 60;
                redisTemplate.opsForValue().set(dataKey, object, ttl, TimeUnit.SECONDS);
            } finally {
                lock.unlock();
            }
        } catch (Exception e) {
            log.info("自定义缓存切面异常：{}", e);
            e.printStackTrace();

        }
        return joinPoint.proceed(args);
    }
}
